﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using NPOI.SS.Formula.Functions;
using System.Threading;
using System.Collections;

namespace NetworkTest
{
    //定义委托-添加结果进字典
    public delegate void AddPingResultDelegate(PingResult2 r2);
    //定义委托-设置单元格背景颜色
    public delegate void SetCellBackColorDelegate(PingResult2 r2);

    //主界面类
    public partial class MainForm : Form
    {
        //创建委托-添加结果
        public AddPingResultDelegate AddPingResult { get; set; }
        //创建委托-设置单元格背景颜色
        public SetCellBackColorDelegate SetCellBackColor { get; set; }
        //日志记录器
        public Logger Logger = new Logger();
        //模板路径
        public string TemplateFilePath = $"{Application.StartupPath}\\{Program.TEMPLATE_NAME}";
        //
        public string OpenDir = Application.StartupPath;
        //测试互联网主机
        private readonly string InternetHost = "baidu.com";
        private readonly PingProcess InternetHostPing;
        private bool InternetConnectable = false;
        private int InternetHostTimeDelay = 0;
        //定义一个键值对集合
        public Dictionary<string, PingResult2> PingResultDictionary { get; set; }
        //锁
        private static readonly object DictionaryLock = new object();

        //构造方法
        public MainForm()
        {
            //初始化组件
            InitializeComponent();
            MacTextBox.Text = IPHelper.GetMacList();
            PingResultDictionary = new Dictionary<string, PingResult2>();
            //委托方法指向
            AddPingResult += AddResult;
            SetCellBackColor += SetBackColor;
            //测试连接互联网
            InternetHostPing = new PingProcess(InternetHost);

            //判断模板文件是否存在
            if (File.Exists(TemplateFilePath))
            {
                //加载模板文件
                LoadTemplateFile(TemplateFilePath);
                FilePathTextBox.Text = TemplateFilePath;
            }
            else
            {
                //提示模板文件不存在
                Logger.Log($"模板文件不存在！请将模板文件放在程序目录下！模板文件名：{Program.TEMPLATE_NAME}");
            }
        }

        //加载模板文件
        private void LoadTemplateFile(string path)
        {
            try
            {
                //读取项目名称
                string projectName = ExcelHelper.ReadProjectName(path);
                Text = $"{projectName}-网络连接情况检测-本机IP：{IPHelper.LocalIPs}";
                ProjectGroupBox.Text = $"项目名称：{projectName}";
                //读取Excel内容写入DataGridView
                List<string[]> list = ExcelHelper.GetContent(path);
                //去重
                list = ListHelper.RemoveRepeat(list);
                //创建结果键值对
                PingResultDictionary = new Dictionary<string, PingResult2>();
                //设置表格列头
                SetDataGridViewColumnHeader(list[0]);

                //遍历
                for (int i = 1; i < list.Count; i++)
                {
                    //获取一行数据
                    string[] row = list[i];
                    //新增一行
                    int index = IPDataGridView.Rows.Add();
                    //设置行头
                    IPDataGridView.Rows[index].HeaderCell.Value = row[0];
                    //遍历
                    for (int j = 1; j < row.Length; j++)
                    {
                        //添加单元格-列坐标，行坐标
                        IPDataGridView[j - 1, index].Value = row[j];
                        //获取列头
                        string columnTitle = IPDataGridView.Columns[j - 1].HeaderText.ToString();
                        //设置提示文本
                        IPDataGridView[j - 1, index].ToolTipText = $"{columnTitle}-{row[0]}-{row[j]}";
                    }
                }
            }
            catch
            {
                //提示
                Logger.Log($"加载模板文件失败!");
                return;
            }

            //提示
            Logger.Log($"模板文件读取成功!");
        }

        //设置表格列头
        private void SetDataGridViewColumnHeader(string[] arr)
        {
            //遍历数组
            for (int i = 1; i < arr.Length; i++)
            {
                //创建列
                DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn();
                //调整列宽
                column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                //禁用排序
                column.SortMode = DataGridViewColumnSortMode.NotSortable;
                //设置列标题
                column.HeaderText = arr[i];
                //添加列             
                IPDataGridView.Columns.Add(column);
            }

            //左上角
            IPDataGridView.TopLeftHeaderCell.Value = arr[0];
        }

        //创建模板按钮单击事件
        private void CreateTemplateButton_Click(object sender, EventArgs e)
        {
            //创建模板
            string path = ExcelHelper.CreateExcelTemplate();
            OpenDir = path;
            if (FilePathTextBox.Text.Length <= 0)
            {
                TemplateFilePath = path;
                FilePathTextBox.Text = path;
            }
            Logger.Log($"创建模板成功！位置：{path}");
        }

        //刷新日志定时器触发事件
        private void LogTimer_Tick(object sender, EventArgs e)
        {
            //有日志
            if (Logger.HasLog())
            {
                LogToolStripStatusLabel.Text = Logger.GetLog();
                //提示文本
                LogToolStripStatusLabel.ToolTipText = LogToolStripStatusLabel.Text;
            }
        }

        //关于按钮单击事件
        private void AboutButton_Click(object sender, EventArgs e)
        {
            MessageBox.Show(Program.APP_ABOUT, "关于");
        }

        //窗口首次显示事件
        private void MainForm_Shown(object sender, EventArgs e)
        {
            LogTimer.Interval = 1000;
            Timer0.Interval = 5000;
            Timer1.Interval = 100;
            Timer2.Interval = 500;
            Timer3.Interval = 10000;
            //启动刷新日志定时器
            LogTimer.Start();
            Timer0.Start();
            Timer1.Start();
            Timer3.Start();
        }

        //状态栏双击事件
        private void LogToolStripStatusLabel_DoubleClick(object sender, EventArgs e)
        {
            //是文件
            if (File.Exists(OpenDir))
            {
                //打开文件夹，选中文件
                Process.Start("explorer.exe", $"/select,{OpenDir}");
            }
            else if (Directory.Exists(OpenDir))
            {
                //打开文件夹
                Process.Start("explorer.exe", OpenDir);
            }
        }

        //Ping按钮单击事件
        private void PingButton_Click(object sender, EventArgs e)
        {
            int deviceCount = DataGridViewHelper.CountDevices(IPDataGridView);
            //如果设备数量大于0
            if (deviceCount > 0)
            {
                //禁用按钮
                PingButton.Enabled = false;
                IPDataGridView[0, 0].Selected = false;
                Logger.Log("正在检测中...");
                //创建结果键值对
                PingResultDictionary = new Dictionary<string, PingResult2>(deviceCount);
                //初始化所有单元格背景白色
                DataGridViewHelper.InitCellsBackground(IPDataGridView, Color.White);
                //获取待检测的IP数组
                string[] ips = DataGridViewHelper.GetIPs(IPDataGridView);

                //循环创建线程
                foreach (string ip in ips)
                {
                    //将方法加入线程池任务队列
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ExcutePing), new Tuple<string, int>(ip, IPHelper.PingRequestsNumber));
                }

            }

        }

        //执行Ping方法
        private void ExcutePing(object obj)
        {
            Tuple<string, int> t = obj as Tuple<string, int>;
            PingResult2 result2 = new PingResult2(t.Item1, false, -1);
            //创建Ping进程
            PingProcess pingProcess = new PingProcess();
            try
            {
                //执行ping
                result2 = pingProcess.Execute(t.Item1, t.Item2);
            }
            catch (Exception) { }

            //添加结果进字典
            AddPingResult(result2);

            //设置单元格背景色
            //SetCellBackColor(result2);
        }

        //添加结果进集合
        private void AddResult(PingResult2 r2)
        {
            //加锁
            lock (DictionaryLock)
            {
                //Console.WriteLine("进入锁");
                if (!PingResultDictionary.ContainsKey(r2.IP))
                {
                    //添加键值对数据,键必须唯一,值可重复
                    PingResultDictionary.Add(r2.IP, r2);
                }
                //Console.WriteLine("退出锁");
            }
        }

        //设置单元格背景色
        private void SetBackColor(PingResult2 r2)
        {
            DataGridViewHelper.SetCellBackColor(IPDataGridView, r2);
        }

        //选择文件按钮单击事件
        private void SelectFileButton_Click(object sender, EventArgs e)
        {
            Logger.Log($"选择模板文件中...");
            //路径文件存在
            if (File.Exists(FilePathTextBox.Text))
            {
                //设置对话框打开时的初始目录
                OpenFileDialog.InitialDirectory = Path.GetDirectoryName(FilePathTextBox.Text);
            }

            //打开选择文件对话框
            OpenFileDialog.ShowDialog();
        }

        //文件选择对话框OK事件
        private void OpenFileDialog_FileOk(object sender, CancelEventArgs e)
        {
            if (OpenFileDialog.FileName.Length > 0)
            {
                //清空表-包括表头
                IPDataGridView.Columns.Clear();
                TemplateFilePath = OpenFileDialog.FileName;
                //加载模板文件
                LoadTemplateFile(TemplateFilePath);
                FilePathTextBox.Text = TemplateFilePath;
            }
        }

        //定时器0触发事件
        private void Timer0_Tick(object sender, EventArgs e)
        {
            //窗口显示后，延迟5秒启动定时器2
            Timer2.Start();
            Timer0.Stop();
        }

        //定时器1触发事件
        private void Timer1_Tick(object sender, EventArgs e)
        {
            //设置状态栏                    
            MousePosToolStripStatusLabel.Text = $"X:{MousePosition.X},Y:{MousePosition.Y}";
            MemoryToolStripStatusLabel.Text = $"消耗内存{ProcessHelper.CurrentMemory()}MB";
            NowTimeToolStripStatusLabel.Text = $"{Tool.NowTime()}";
            //连接互联网检测
            if (InternetConnectable)
            {
                InternetToolStripStatusLabel.Text = $"可以连接互联网-时延{InternetHostTimeDelay}ms";
                InternetToolStripStatusLabel.ForeColor = Color.Green;
            }
            else
            {
                InternetToolStripStatusLabel.Text = "无法连接互联网";
                InternetToolStripStatusLabel.ForeColor = Color.Red;
            }
        }

        //定时器2触发事件
        private void Timer2_Tick(object sender, EventArgs e)
        {
            //设备数量
            int sum = DataGridViewHelper.CountDevices(IPDataGridView);
            int count = DictionaryHelper.CountTrueResult(PingResultDictionary);
            NetworkGroupBox.Text = $"网络检测-[ 设备数量：{sum} ] [ True：{count} ] [ False：{sum - count} ]";
            //检测中
            if (PingResultDictionary.Count > 0 && PingResultDictionary.Count <= sum && PingButton.Enabled == false)
            {
                //设置单元格背景色和提示文本
                DataGridViewHelper.SetCellBackColorAndToolTipText(IPDataGridView, PingResultDictionary);

                //判断是否检测完成
                if (PingResultDictionary.Count == sum)
                {
                    //启用按钮
                    PingButton.Enabled = true;
                    Logger.Log("检测完成！");
                }
            }
        }

        //定时器3触发事件
        private void Timer3_Tick(object sender, EventArgs e)
        {
            //开线程测试连接互联网
            ThreadPool.QueueUserWorkItem(new WaitCallback(ConnectInternet));
        }

        //测试连接互联网
        private void ConnectInternet(object obj)
        {
            //Ping互联网主机
            PingResult2 r2 = InternetHostPing.Execute();
            InternetConnectable = r2.State;
            InternetHostTimeDelay = r2.TimeDelay;
        }

        //获取MAC地址按钮单击事件
        private void GetMacButton_Click(object sender, EventArgs e)
        {
            MacTextBox.Text = IPHelper.GetMacList();
            Logger.Log("获取Mac地址表成功!");
        }

        //主窗口关闭事件
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            //停止定时器
            LogTimer.Stop();
            Timer0.Stop();
            Timer1.Stop();
            Timer2.Stop();
            Timer3.Stop();
        }
    }
}
